#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>

#include "PGPLOT_Renderer.h"
#include "DataContainer.h"

#include "cpgplot.h"

PGPLOT_Renderer::PGPLOT_Renderer() {

	cout << "PGPLOT_Renderer::PGPLOT_Renderer Default Constructor" << endl;
	
	this->device = NULL;
	this->verbose = false;
	xmin=-43200;
	xmax=43200;
	ymin=-324000.;
	ymax=324000.;

	title = "PGPLOT BLANK FRAME";
	xlabel = "X Axis";
	ylabel = "Y Axis";

	x_options = "ABCNSTZH";
	y_options = "ABCNSTZD";

	num_levels = 64;

}

PGPLOT_Renderer::~PGPLOT_Renderer() {

	cout << "PGPLOT_Renderer::~PGPLOT_Renderer Default Destructor" << endl;

}
void PGPLOT_Renderer::set_device(char *dev) {

	device = strdup(dev);

}
void PGPLOT_Renderer::set_numlevels(int nl) {

	num_levels = nl;
}
int PGPLOT_Renderer::init() {

	
	if (device == NULL) {
		cout << "PGPLOT_Renderer::init using default device " << DEFAULT_DEV << endl;
		set_device((char *) DEFAULT_DEV);

	}

	cpgopen(device);
	ColourMap = new PGPLOT_gray;
	ColourMap->build_table(0);

 	return EXIT_SUCCESS;

}
void PGPLOT_Renderer::set_window(float min_ra_hours, float max_ra_hours, float min_dec_deg, float max_dec_deg) {

	xmin = min_ra_hours * 60.0 * 60.0;
	xmax = max_ra_hours * 60.0 * 60.0;

	ymin = min_dec_deg * 60.0 * 60.0;	
	ymax = max_dec_deg * 60.0 * 60.0;
	draw_frame();

       
}
void PGPLOT_Renderer::set_labels(string t, string xl, string yl) {

	title = t;
	xlabel=xl;
	ylabel=yl;
}	
int PGPLOT_Renderer::draw_frame() {

	cout << "PGPLOT_Renderer::draw() Drawing Member Function" << endl;
	cpgeras();
 	cpgswin(xmin,xmax,ymin,ymax);
	cpgtbox(x_options.c_str(),0.0,0.0,y_options.c_str(),0.0,0.0);
	cpglab(xlabel.c_str(),ylabel.c_str(),title.c_str());

	return EXIT_SUCCESS;
		
}
int PGPLOT_Renderer::draw_pixels(DataContainer *container) {

	// First need to get the number of pixels

	int npix = container->ndata;
	
	vector<float> ranges;
	vector<float> values;
	vector<float> vertices;
	vector<float> point;
	vector<float> locus;
	point.resize(2);
	vertices.resize(8);
	float increment;
	float colour;
	container->Get_Val_Limits(ranges);
	if (npix > 0) {

		cout << "Will attempt to render " << npix << " pixels onto device" << endl;

		for (int pix = 0; pix < npix ; pix++) {

			container->Get_Pix_Val(pix,values);
			container->Get_Pix_Vertices(pix,point,vertices,locus);
			if (verbose == true) {
				cout << "Pixel: " << pix << endl;
				for (unsigned int i=0; i < values.size();i++) {
					cout << " Val: " << values[i] << " Range[" << ranges[i*2] << ":" << ranges[i*2+1] << "]" << endl;
					for (unsigned v = 0; v < 8; v=v+2){
						cout << "[" << vertices[v] << "," << vertices[v+1] << "] ";
					}
					cout << endl;
				}
			}
			/* need to get the colour index */
			increment = ColourMap->set_range(ranges[0],ranges[1]);
			colour = floorf((values[0] - ranges[0])/increment);
			cpgsfs(1);
			cpgsci(int(colour));
			// draw_pixel(vertices,values[0]);
			draw_pixel(vertices,values[0]);
			draw_point(point[0],point[1],1);
		}
	}
	else {
		cout << "Container has no pixels (perhaps a function?) " << endl;
	}
	cpgclos();
	return EXIT_FAILURE;
	
}
	
void PGPLOT_Renderer::draw_point(float xin, float yin, int symbol) {
	float x = (M_PI - xin) * 12.0/M_PI * 60. * 60.;	
	float y =  yin * 180.0/M_PI * 60. * 60.;	
	cpgpt1(x,y,symbol);
}

void PGPLOT_Renderer::draw_pixel(vector<float>& vertices, float value) {
	
	vector<float> xpts;
	vector<float> ypts;

		/* yes some hard coding here ... should make this much more general but time is pressing */

	int npts = vertices.size()/2;
	xpts.resize(npts);
	ypts.resize(npts);

	for (int i=0;i<npts;i++) {
		xpts[i] = (M_PI - vertices[2*i]) * 12.0/M_PI * 60. * 60.;		
		ypts[i] = (M_PI/2.0 - vertices[2*i+1]) * 180.0/M_PI * 60. * 60.;		
        }
		/* need to calculate the required colour here */

		/* then set the fill area attribute */

		/* then render the pixel */
	cpgbbuf();
	//	cpgsci(1);
	if (verbose == true) {
		cout << "planting polygon: " ;

		for (int i=0; i<npts; i++) {
			cout << "[" << xpts[i] << "," << ypts[i] << "]" << endl;
		}
	}
	cpgpoly(npts,(float *) &xpts[0], (float *) &ypts[0]);
	cpgebuf();
}
		

